package com.dtwave.wechat.service.provider.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.dtwave.wechat.service.provider.common.enums.ApplicationEnum;
import com.dtwave.wechat.service.provider.common.enums.UserStatusEnum;
import com.dtwave.wechat.service.provider.common.model.AddressBookEntity;
import com.dtwave.wechat.service.provider.common.model.AddressBookResult;
import com.dtwave.wechat.service.provider.common.model.AddressDpartmentEntity;
import com.dtwave.wechat.service.provider.common.model.AddressDpartmentResult;
import com.dtwave.wechat.service.provider.common.utils.Conversion;
import com.dtwave.wechat.service.provider.common.utils.FileUtils;
import com.dtwave.wechat.service.provider.common.utils.URLEncodeUtil;
import com.dtwave.wechat.service.provider.core.wx.WeiXinApi;
import com.dtwave.wechat.service.provider.core.wx.WeiXinMakeToken;
import com.dtwave.wechat.service.provider.core.wx.WeiXinMethodUtil;
import com.dtwave.wechat.service.provider.database.entity.Office;
import com.dtwave.wechat.service.provider.database.entity.UserEntity;
import com.dtwave.wechat.service.provider.service.IOfficeService;
import com.dtwave.wechat.service.provider.service.IWeChatInterfaceService;
import com.dtwave.wechat.service.provider.service.UserService;
import com.google.gson.Gson;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Auther: liuwenxiang
 * @Date: 2019/2/23 17:51
 * @Description:
 */
@Service
public class WeChatInterfaceImpl implements IWeChatInterfaceService {

    private static Logger logger = LoggerFactory.getLogger(WeChatInterfaceImpl.class);

    @Autowired
    IOfficeService iOfficeService;

    @Autowired
    UserService userService;

    @Autowired
    WeiXinMakeToken weiXinMakeToken;

    @Value("${ht.passWord}")
    private  String passWord;

    @Value("${spring.resources.static-locations}")
    private  String fileDir;



    @Override
    @Transactional
    public boolean synchTxl(){
        try{
            synchDepartment();
            synchUser();
        }catch (Exception e){
            logger.error("通讯录同步异常",e);
            return false;
        }
        return true;
    }





    @Override
    public String getWxAmr(String mediaId,String type, HttpServletRequest request) throws Exception{
        //1.通过type，选择token
        String token="";
        if((ApplicationEnum.TZTB.getCode()).equals(type)){
            token = WeiXinMakeToken.accessToken_tztb.getToken();
        }else if((ApplicationEnum.XXSB.getCode()).equals(type)){
            token = WeiXinMakeToken.accessToken_xxsb.getToken();
        }
        //2.通过media获取文件流
        InputStream in = getWxAmr(mediaId,token);
        //3.存储文件
        //3.1.构建目录和文件
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date =sdf.format(new Date())+"/voices";
        String fileSplit = fileDir .split(":")[1];
        String dir = fileSplit+"/"+date;
        String random = "Wx_" + URLEncodeUtil.getRandomString(10);
        String amr = random+".amr";
        String mp3 = random+".mp3";
        //3.2.创建目录和文件
        FileUtils.createDirectory(dir);
        FileUtils.createFile(dir+"/"+amr);
        byte[] btImg = readInputStream(in);
        if (null != btImg && btImg.length > 0) {
            //3.3.文件上传
            writeAmrToDisk(btImg,dir+"/"+amr);
            //4.文件格式转换
            Conversion.ToMp3(dir+"/"+amr,dir+"/"+mp3);//savePath：amr文件存放的全路径
        }else{
            throw new Exception();
        }

        //5.返回转码后的音频文件
        return date+"/"+mp3;
    }

    /**
     * 增量同步
     * @return
     */
    public void synchDepartment(){
        //查询后台组织架构
        Map<Integer,Office> dbMap = new HashMap<Integer,Office>();
        Map<Integer,Boolean> dbMap1 = new HashMap<Integer,Boolean>();
        List<Office> officeList = iOfficeService.selectList(null);
        if (CollectionUtils.isNotEmpty(officeList)) {
            for (int i = 0; i < officeList.size(); i++) {
                Office office = officeList.get(i);
                dbMap.put(office.getOfficeId(),office);
                dbMap1.put(office.getOfficeId(),true);
            }
        }

        //查询企业微信组织架构
        String dataPartment = WeiXinMethodUtil.getDepartmentList(WeiXinMakeToken.accessToken_txl.getToken());
        Gson gPartment = new Gson();
        AddressDpartmentResult apr = gPartment.fromJson(dataPartment, AddressDpartmentResult.class);
        if (apr != null && apr.getDepartment() != null) {
            for (int i = 0; i < apr.getDepartment().size(); i++) {
                AddressDpartmentEntity ape = apr.getDepartment().get(i);
                if(dbMap.get(ape.getId())!=null){//修改db中的部门信息
                    Office office = dbMap.get(ape.getId());
                    office.setOfficeId(ape.getId());
                    office.setParentId(String.valueOf(ape.getParentid()));
                    office.setOfficeName(ape.getName());
                    iOfficeService.updateById(office);
                    dbMap1.put(ape.getId(),false);
                }else{//新增一条组织信息到db中
                    Office office=new Office();
                    office.setOfficeId(ape.getId());
                    office.setParentId(String.valueOf(ape.getParentid()));
                    office.setOfficeName(ape.getName());
                    iOfficeService.insert(office);
                }
            }
            //删除db中的部门信息（在微信端已经删除的部门信息）
            Iterator<Map.Entry<Integer,Boolean>> it = dbMap1.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Integer,Boolean> entry = it.next();
                if(entry.getValue()){
                    iOfficeService.deleteById(entry.getKey());
                }
            }
        }
    }



    public void synchUser(){
        //查询db中的所有用户
        Wrapper<UserEntity> wrapper = new EntityWrapper<UserEntity>();
        wrapper.eq("status", UserStatusEnum.NOTLEAVE.getCode());//在职
        List<UserEntity> userList = userService.selectList(wrapper);
        Map<String,UserEntity> dbMap = new HashMap<String,UserEntity>();
        Map<String,Boolean> dbMap1 = new HashMap<String,Boolean>();

        ArrayList<String> dbList = new ArrayList<String>();
        if(CollectionUtils.isNotEmpty(userList)){
            for (UserEntity userEntity:userList) {
                dbMap.put(userEntity.getUserId(),userEntity);
                dbMap1.put(userEntity.getUserId(),true);
            }
        }
        //查询每个部门下的用户，与db中进行对比同步
        /**同步规则：
         * 1.db不存在，微信端存在，新增到db
         * 2.db中存在，微信端存在，更新到db
         * 3.db中存在，微信端不存在，置为离职
         */
        List<Office> officeList = iOfficeService.selectList(null);
        if(CollectionUtils.isNotEmpty(officeList)){
            //用户去重：存放查询到的每个部门下的用户
            Set set = new HashSet();
            for (Office office:officeList) {
                // 获取部门成员列表(部门id，0只同步当前部门下的数据)
                String dataUser = WeiXinMethodUtil.getSimpleList(String.valueOf(office.getOfficeId()), "0", 0, WeiXinMakeToken.accessToken_txl);
                Gson gUser = new Gson();
                AddressBookResult abr = gUser.fromJson(dataUser, AddressBookResult.class);
                if (abr != null && abr.getUserlist() != null) {
                    for (int i = 0; i < abr.getUserlist().size(); i++) {
                        AddressBookEntity wxUser = abr.getUserlist().get(i);
                        String userId = wxUser.getUserid();
                        if(!set.add(userId)) {continue;}
                        if (dbMap.get(userId) != null) {//修改db中的部门信息
                            UserEntity userEntity = dbMap.get(userId);
                            setUserEntity(wxUser, userEntity);
                            userService.updateById(userEntity);
                            //将微信端和db中都有的用户从dbList从移除，最后获取微信端已经删除，db还存在的用户，并在后面将其置为离职
                            dbMap1.put(userId,false);
                        } else {//新增一条组织信息到db中
                            /**重新入职情行：
                             * 新增用户时，先判断是否存在已经离职的用户，重新入职；若存在，就无需新增，直接将之前的进行更新
                             * (极其少情形：对于一个手机号，a用了之后，废弃后，b用了，这种特殊情况，遇到了再处理数据)
                             */
                            Wrapper<UserEntity> wrapper1 = new EntityWrapper<UserEntity>();
                            wrapper1.eq("user_id",userId );
                            wrapper1.eq("status", UserStatusEnum.LEAVE.getCode());//离职
                            List<UserEntity> userList1 = userService.selectList(wrapper1);
                            if(CollectionUtils.isNotEmpty(userList1)){
                                UserEntity leaveUser = userList1.get(0);
                                leaveUser.setStatus(UserStatusEnum.NOTLEAVE.getCode());
                                setUserEntity(wxUser, leaveUser);
                                userService.updateById(leaveUser);
                            }else{
                                UserEntity userEntity = new UserEntity();
                                setUserEntity(wxUser, userEntity);
                                userEntity.setPassWord(passWord);//后台系统的初始密码
                                userEntity.setStatus(UserStatusEnum.NOTLEAVE.getCode());//在职
                                userService.insert(userEntity);
                            }
                        }
                    }
                }
            }
            //将微信端已删除的用户置为离职
            Iterator<Map.Entry<String,Boolean>> it = dbMap1.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String,Boolean> entry = it.next();
                if(entry.getValue()){
                    UserEntity userEntity = new UserEntity();
                    userEntity.setUserId(entry.getKey());
                    userEntity.setStatus(UserStatusEnum.LEAVE.getCode());//离职
                    userService.updateById(userEntity);
                }
            }
            //将部门与用户进行关联
            Wrapper<UserEntity> wrapper2 = new EntityWrapper<UserEntity>();
            wrapper.eq("status", UserStatusEnum.NOTLEAVE.getCode());//离职
            List<UserEntity> finallyUserList = userService.selectList(wrapper2);
            //删除先前的关联关系
            userService.delUserOfficeRelation();
            for(UserEntity finallyUser:finallyUserList){
                String userId = finallyUser.getUserId();
                String department = finallyUser.getDepartment();
                String[] departmentArr = department.replace("[","").replace("]","").split(",");
                if(departmentArr!=null &&departmentArr.length>0){
                    for (String dp:departmentArr) {
                        Integer dpInter = Integer.valueOf(dp.trim());
                        //插入新的关联关系
                        userService.addUserOfficeRelation(userId,dpInter);
                    }
                }

            }
        }
    }

    private void setUserEntity(AddressBookEntity wxUser, UserEntity userEntity) {
        userEntity.setUserId(wxUser.getUserid());
        userEntity.setUserName(wxUser.getName());
        userEntity.setLoginName(wxUser.getMobile());
        userEntity.setDepartment(wxUser.getDepartment().toString());
        userEntity.setMobile(wxUser.getMobile());
        userEntity.setPhone(wxUser.getTelephone());
        userEntity.setGender(wxUser.getGender());
        userEntity.setEmail(wxUser.getEmail());
        userEntity.setAvatar(wxUser.getAvatar());
        userEntity.setWeixinid(wxUser.getWeixinid());
        userEntity.setWeixinStatus(wxUser.getStatus());
    }






    public InputStream getWxAmr(String mediaId,String token){
        String url = WeiXinApi.download_voice.replace("ACCESS_TOKEN", token).replace("MEDIA_ID",mediaId);
        InputStream is = null;
        try {
            System.out.println(url);
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setConnectTimeout(5000);
            http.setReadTimeout(5000);
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 不设置这个属性，会导致不能从微信端下载资源
            http.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
            http.setDoOutput(true);
            http.setDoInput(true);
            http.connect();
            System.out.println(http.getContentType());
            // 获取文件转化为byte流
            is = http.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return is;
    }


    /**
     * 从输入流中获取数据
     *
     * @param inStream
     *            输入流
     * @return
     * @throws Exception
     */
    public  byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }

    /**
     * 将录音写入到磁盘
     *            文件保存时的名称
     */
    public  void writeAmrToDisk(byte[] amr,String savePath) {
        try {
            File file = new File(savePath);
            FileOutputStream fops = new FileOutputStream(file);
            fops.write(amr);
            fops.flush();
            fops.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
